package com.seari.custody.service.Impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aspose.words.Document;
import com.aspose.words.SaveFormat;
import com.google.api.client.util.Lists;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import com.seari.custody.bean.*;
import com.seari.custody.component.MinIoUtil;
import com.seari.custody.component.OutlineProjectCalc;
import com.seari.custody.enums.MeetingFileType;
import com.seari.custody.enums.OutLineProjectStatus;
import com.seari.custody.exception.BIZException;
import com.seari.custody.mapper.OutlineProjectMapper;
import com.seari.custody.mapper.ReportProjectMapper;
import com.seari.custody.mapper.TechnicalAdviceMapper;
import com.seari.custody.service.MeetingFileService;
import com.seari.custody.service.OutLineProjectService;
import com.seari.custody.util.HttpClientUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.InputStreamSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.*;

import static com.seari.custody.util.Common.getLicense;

@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class OutlineProjectServiceImpl implements OutLineProjectService {
    @Autowired
    private OutlineProjectMapper outlineProjectMapper;
    @Autowired
    private OutlineProjectCalc outlineProjectCalc;
    @Autowired
    private ProjectServiceImpl projectService;
    @Autowired
    private ReportProjectMapper reportProjectMapper;
    @Autowired
    private TechnicalAdviceMapper technicalAdviceMapper;
    @Autowired
    private MeetingFileService meetingFileService;
    @Autowired
    private MinIoUtil minIoUtil;
    @Value("${push.outline.js}")
    private String pushOutlineJS;
    @Autowired
    private HttpClientUtil httpClientUtil;

    @Override
    public Integer countByProjectId(String projectId) {
        OutlineProjectExample outlineProjectExample = new OutlineProjectExample();
        outlineProjectExample.createCriteria().andProjectIdEqualTo(projectId);


        List<OutlineProject> outlineProjects = outlineProjectMapper.selectByExample(outlineProjectExample);
        if (CollectionUtil.isEmpty(outlineProjects)) {
            return 0;
        }
        return outlineProjects.size();
    }

    @Override
    public Map<String, Object> getOutLineProjectByProjectId(String projectId) {
        OutlineProjectExample outlineProjectExample = new OutlineProjectExample();
        outlineProjectExample.createCriteria().andProjectIdEqualTo(projectId);
        outlineProjectExample.setOrderByClause("create_time desc");

        List<OutlineProject> outlineProjects = outlineProjectMapper.selectByExample(outlineProjectExample);

        if (CollectionUtil.isEmpty(outlineProjects)) {
            return null;
        }
        HashMap<String, Object> result = Maps.newHashMap();
        List<Object> dates = Lists.newArrayList();
        for (OutlineProject outlineProject : outlineProjects) {
            dates.add(OutLineDateHistory.builder().date(outlineProject.getCreateTime()).msg(OutLineProjectStatus.getMsg(outlineProject.getAckMsg())).ackMsg(outlineProject.getAckMsg()).build()
            );
        }

        result.put("dates", dates);
        result.put("data", outlineProjects.get(0));

        return result;

    }

    @Override
    public OutlineProject qryOneByProjectIdAndCreateTime(String projectId, String createTime) {
        OutlineProjectExample outlineProjectExample = new OutlineProjectExample();
        outlineProjectExample.createCriteria().andProjectIdEqualTo(projectId).andCreateTimeEqualTo(DateUtil.parse(createTime, DatePattern.NORM_DATETIME_PATTERN));

        List<OutlineProject> outlineProjects = outlineProjectMapper.selectByExample(outlineProjectExample);
        return outlineProjects.get(0);
    }


    @Override
    public void saveOutLineProject(OutlineProject outlineProject) {
        outlineProjectMapper.insert(outlineProject);
    }

    @Override
    public Integer updateOutLineProject(OutlineProject outlineProject) {
        outlineProject.setUpdateTime(new Date());
        return outlineProjectMapper.updateByPrimaryKeySelective(outlineProject);
    }

    @Override
    public void genData(OutlineProjectData outlineProjectData) {
        Project project1 = projectService.qryByProjectId(outlineProjectData.getProjectId());
        String outlineStatus = project1.getOutlineStatus();
        if (Objects.equals(outlineStatus, OutLineProjectStatus.DATA_MODIFY_ACK.getStatusCode())) {
            throw new BIZException("技术要求表已确认,不可再生成");
        }

        OutlineProject outlineProject = outlineProjectCalc.getOutlineProject(outlineProjectData);

        outlineProject.setId(IdUtil.objectId());
        outlineProject.setAckMsg(OutLineProjectStatus.PROCESSING.getStatusCode());
        outlineProjectMapper.insertSelective(outlineProject);

        //更新project状态
        Project project = new Project();
        project.setUuid(outlineProjectData.getProjectId());
        project.setOutlineStatus(OutLineProjectStatus.PROCESSING.getStatusCode());
        projectService.updProject(project);

        // 历史记录-监护大纲处理中
        Map<String, Object> stringIntegerMap = reportProjectMapper.saverFileNumber(outlineProjectData.getProjectId());
        Integer flow_number = Integer.valueOf(stringIntegerMap.get("flow_number").toString());
        TechnicalHistory technicalHistory = new TechnicalHistory();
        technicalHistory.setCreateTime(new Date());
        technicalHistory.setOperationalType("2");
        technicalHistory.setOperationalFlow("3");
        technicalHistory.setOperationalContext("监护大纲处理中");
        technicalHistory.setOperationalOperator(project.getManagerNumber());
        technicalHistory.setOperationalState("1");
        technicalHistory.setOperationalProject(outlineProjectData.getProjectId());
        technicalHistory.setOperationalNumber(flow_number);
        technicalAdviceMapper.serverTechnicalHistory(technicalHistory);
    }


    @Override
    public Map<String, String> level(List<OutlineProjectData> dataList) {
        OutlineProjectData outlineProjectData1 = dataList.get(0);

        Integer level = 10;
        OutlineProjectData od = null;
        for (OutlineProjectData outlineProjectData : dataList) {
            try {
                Integer l = outlineProjectCalc.calculateLevel(outlineProjectData);
                if (l < level) {
                    level = l;
                    od = outlineProjectData;
                }
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        }

        int i = level + outlineProjectData1.getAdjustLevel();
        int i1 = i <= 0 ? 1 : i;
        HashMap<String, String> objectObjectHashMap = Maps.newHashMap();
        objectObjectHashMap.put("level", String.valueOf(Math.min(i1, 4)));
        //取监护等级最高的覆土 f
        if (od != null) {
            if (od.getF() != null) {
                objectObjectHashMap.put("f", String.valueOf(od.getF()));
            } else {
                objectObjectHashMap.put("f", "0");
            }
        } else {
            objectObjectHashMap.put("f", "0");
        }
        return objectObjectHashMap;
    }

    @Override
    public OutlineParseVO getProjectInfo(String projectId) {
        //先查自己
        OutlineProjectExample outlineProjectExample = new OutlineProjectExample();
        outlineProjectExample.createCriteria().andProjectIdEqualTo(projectId);
        List<OutlineProject> outlineProjects = outlineProjectMapper.selectByExample(outlineProjectExample);
        OutlineParseVO outlineParseVO = new OutlineParseVO();

        if (CollectionUtil.isEmpty(outlineProjects)) {
            Project project = projectService.qryByProjectId(projectId);
            if (project != null) {
                String projectType = project.getProjectType();
                if (projectType != null) {
                    //当技审意见项目类别为拆除、勘探、绿化、市政 等于 监护大纲 加卸载、管线、桥梁、桩基及其他类
                    switch (projectType) {
                        case "1":
                            project.setProjectType("1");
                            break;
                        case "6":
                            project.setProjectType("2");
                            break;
                        default:
                            project.setProjectType("3");
                            break;
                    }

                }
                BeanUtils.copyProperties(project, outlineParseVO);
            }
        } else {
            BeanUtils.copyProperties(outlineProjects.get(0), outlineParseVO);
        }
        return outlineParseVO;
    }

    /**
     * 推送技术要求数据到计审
     */
    @Override
    public void pushData2JS(String projectId) {
        OutlineProjectExample outlineProjectExample = new OutlineProjectExample();
        outlineProjectExample.createCriteria().andProjectIdEqualTo(projectId);
        outlineProjectExample.setOrderByClause("update_time desc");
        List<OutlineProject> outlineProjects = outlineProjectMapper.selectByExample(outlineProjectExample);
        if (CollectionUtil.isNotEmpty(outlineProjects)) {
            OutlineProject outlineProject = outlineProjects.get(0);
            Project project = projectService.qryByProjectId(projectId);
            Outline2JSDTO outline2JSDTO = new Outline2JSDTO();
            outline2JSDTO.setNo(project.getNo());
            outline2JSDTO.setPersonNumber(project.getManagerNumber());
            outline2JSDTO.setType(project.getType());
            outline2JSDTO.setResult("同意");
            outline2JSDTO.setOutlineInfo(outlineProject);
            String body = JSON.toJSONString(outline2JSDTO);
            HttpRequest body1 = HttpUtil.createPost(pushOutlineJS).body(body).header("Content-Type", "application/json;charset=UTF-8").header("Accept", "application/json");
            String body2 = body1.execute().body();
            JSONObject jsonObject = JSON.parseObject(body2);
            if (Objects.equals(jsonObject.get("status"), "500")) {
                throw new BIZException("推送失败:" + jsonObject.get("message"));
            }
            outlineProject.setAckMsg(OutLineProjectStatus.HAS_BEEN_SENT.getStatusCode());
            outlineProjectMapper.updateByPrimaryKeySelective(outlineProject);

            //更新project状态
            project.setOutlineStatus(OutLineProjectStatus.HAS_BEEN_SENT.getStatusCode());
            projectService.updProject(project);

            // 历史记录-已发送
            Map<String, Object> stringIntegerMap = reportProjectMapper.saverFileNumber(projectId);
            Integer flow_number = Integer.valueOf(stringIntegerMap.get("flow_number").toString());
            TechnicalHistory technicalHistory = new TechnicalHistory();
            technicalHistory.setCreateTime(new Date());
            technicalHistory.setOperationalType("2");
            technicalHistory.setOperationalFlow("4");
            technicalHistory.setOperationalContext(project.getProjectName() + "监护大纲发送");
            technicalHistory.setOperationalOperator(project.getManagerNumber());
            technicalHistory.setOperationalState("1");
            technicalHistory.setOperationalProject(projectId);
            technicalHistory.setOperationalNumber(flow_number);
            technicalAdviceMapper.serverTechnicalHistory(technicalHistory);
        }

    }

    @Override
    public void feedBack(OutlineProject outlineProject) {
        if (Strings.isNullOrEmpty(outlineProject.getAckMsg())) {
            throw new BIZException("[ackMsg]不可为空");
        }
        List legalParams = com.google.common.collect.Lists.newArrayList("5", "6", "7");
        if (!legalParams.contains(outlineProject.getAckMsg())) {
            throw new BIZException("[ackMsg]参数非法");
        }
        Project project1 = projectService.qryByNo(outlineProject.getProjectId());
        Project project = new Project();
        project.setOutlineStatus(outlineProject.getAckMsg());
        project.setUuid(project1.getUuid());
        projectService.updProject(project);

        if (Objects.equals(OutLineProjectStatus.DATA_MODIFY_ACK.getStatusCode(), outlineProject.getAckMsg())) {
            outlineProject.setId(IdUtil.objectId());
            outlineProject.setCreateTime(null);
            outlineProject.setUpdateTime(null);
            outlineProject.setProjectId(project1.getUuid());
            outlineProjectMapper.insertSelective(outlineProject);

            // 历史记录-技术要求表被退回待处理
            Map<String, Object> stringIntegerMap = reportProjectMapper.saverFileNumber(outlineProject.getProjectId());
            Integer flow_number = Integer.valueOf(stringIntegerMap.get("flow_number").toString());
            TechnicalHistory technicalHistory = new TechnicalHistory();
            technicalHistory.setCreateTime(new Date());
            technicalHistory.setOperationalType("2");
            technicalHistory.setOperationalFlow("6");
            technicalHistory.setOperationalContext("技术要求表被修改待确认");
            technicalHistory.setOperationalOperator(project.getManagerNumber());
            technicalHistory.setOperationalState("1");
            technicalHistory.setOperationalProject(outlineProject.getProjectId());
            technicalHistory.setOperationalNumber(flow_number);
            technicalAdviceMapper.serverTechnicalHistory(technicalHistory);


        } else if (Objects.equals(OutLineProjectStatus.DATA_REJECT_PROCESSED.getStatusCode(), outlineProject.getAckMsg())) {
            OutlineProjectExample outlineProjectExample = new OutlineProjectExample();
            outlineProjectExample.createCriteria().andProjectIdEqualTo(project1.getUuid());
            outlineProjectExample.setOrderByClause("update_time desc");
            String id = outlineProjectMapper.selectByExample(outlineProjectExample).get(0).getId();
            OutlineProject outlineProject1 = new OutlineProject();
            outlineProject1.setId(id);
            outlineProject1.setAckMsg(outlineProject.getAckMsg());
            outlineProject.setUpdateTime(new Date());
            outlineProjectMapper.updateByPrimaryKeySelective(outlineProject1);

            // 历史记录-技术要求表被退回待处理
            Map<String, Object> stringIntegerMap = reportProjectMapper.saverFileNumber(outlineProject.getProjectId());
            Integer flow_number = Integer.valueOf(stringIntegerMap.get("flow_number").toString());
            TechnicalHistory technicalHistory = new TechnicalHistory();
            technicalHistory.setCreateTime(new Date());
            technicalHistory.setOperationalType("2");
            technicalHistory.setOperationalFlow("5");
            technicalHistory.setOperationalContext("技术要求表被退回待处理");
            technicalHistory.setOperationalOperator(project.getManagerNumber());
            technicalHistory.setOperationalState("1");
            technicalHistory.setOperationalProject(outlineProject.getProjectId());
            technicalHistory.setOperationalNumber(flow_number);
            technicalAdviceMapper.serverTechnicalHistory(technicalHistory);

        }
    }

    /**
     * 生成报价清单
     *
     * @param projectId
     * @return
     */
    @SneakyThrows
    @Override
    public String genPriceList(String projectId) {
        OutlineProjectExample outlineProjectExample = new OutlineProjectExample();
        outlineProjectExample.createCriteria().andProjectIdEqualTo(projectId);
        outlineProjectExample.setOrderByClause("create_time desc");

        Project project = projectService.qryByProjectId(projectId);

        String fileName = project.getProjectName() + "-监护报价清单.xlsx";


        OutlineProject outlineProject = outlineProjectMapper.selectByExample(outlineProjectExample).stream().findFirst().orElseThrow(() -> new BIZException(""));


        InputStreamSource inputStream = outlineProjectCalc.genPriceList(outlineProject);
        MeetingFile meetingFile = new MeetingFile();
        meetingFile.setMeetingId(projectId);
        meetingFile.setFileName(fileName);
        meetingFile.setFileType(MeetingFileType.PRICE_LIST.getCode());
        String id = IdUtil.objectId();
        meetingFile.setId(id);
        meetingFile.setFileExt("xlsx");
        String path = id + ".xlsx";
        meetingFile.setFilePath(path);
        meetingFileService.uploadFile(meetingFile);
        minIoUtil.putObject(MinIoUtil.MEETING_BUCKET, path, inputStream.getInputStream());
        return id;
    }

    @SneakyThrows
    @Override
    public String getOutlineProjectFile(String projectId, String userNumber, MeetingFileType meetingFileType) {
        MeetingFile meetingFile = meetingFileService.downloadMeetingFile(meetingFileType.getCode(), projectId);
        if (meetingFile == null) {
            if (meetingFileType.equals(MeetingFileType.OUTLINE_PROJECT_WORD)) {
                throw new BIZException("尚无监护大纲文档");
            } else {
                meetingFile = meetingFileService.downloadMeetingFile(MeetingFileType.OUTLINE_PROJECT_WORD.getCode(), projectId);
            }
        }
        if (meetingFile == null) {
            throw new BIZException("尚无监护大纲文档");
        }
        //文件没有下载到minio filePath 暂存ecmId
        String filePath = meetingFile.getId() + "." + meetingFile.getFileExt();

        if (!Objects.equals(meetingFile.getFilePath(), filePath)) {
            InputStream inputStream = httpClientUtil.downRecodeFileAsStream(meetingFile.getFilePath(), meetingFile.getFileName(), userNumber);
            //doc 转docx
            if (Objects.equals("doc", meetingFile.getFileExt())) {
                try (
                        ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream(); BufferedOutputStream os = new BufferedOutputStream(arrayOutputStream)) {
                    if (!getLicense()) {
                        throw new Exception("加载license失败");
                    }
                    Document doc = new Document(inputStream);
                    doc.save(os, SaveFormat.DOCX);
                    inputStream = new ByteArrayResource(arrayOutputStream.toByteArray()).getInputStream();
                }
            }
            //inputStream copy
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            IoUtil.copy(inputStream, byteArrayOutputStream);
            filePath = FileNameUtil.getPrefix(filePath) + ".docx";
            minIoUtil.putObject(MinIoUtil.MEETING_BUCKET, filePath, new ByteArrayResource(byteArrayOutputStream.toByteArray()).getInputStream());
            meetingFile.setFilePath(filePath);
            meetingFile.setFileName(FileNameUtil.getPrefix(meetingFile.getFileName()) + ".docx");
            meetingFile.setUserNumber(userNumber);
            meetingFile.setFileExt("docx");
            meetingFileService.updMeetingFileById(meetingFile);
//            183755
            //转pdf并存储
            if (!getLicense()) {
                throw new Exception("加载license失败");
            }
            try (
                    ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream(); BufferedOutputStream os = new BufferedOutputStream(arrayOutputStream)) {
                Document doc = new Document(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
                doc.save(os, SaveFormat.PDF);
                String id = IdUtil.objectId();
                String path = id + ".pdf";
                InputStream inputStream1 = new ByteArrayResource(arrayOutputStream.toByteArray()).getInputStream();
                minIoUtil.putObject(MinIoUtil.MEETING_BUCKET, path, inputStream1);
                MeetingFile meetingFile1 = new MeetingFile();

                meetingFile1.setMeetingId(projectId);
                meetingFile1.setFileType(MeetingFileType.OUTLINE_PROJECT_PDF.getCode());
                meetingFile1.setId(id);
                meetingFile1.setUserNumber(userNumber);
                meetingFile1.setFileExt("pdf");
                meetingFile1.setFilePath(path);
                meetingFile1.setFileName(FileNameUtil.getPrefix(meetingFile.getFileName()) + ".pdf");
                meetingFileService.uploadFile(meetingFile1);
                return minIoUtil.genShareLink(MinIoUtil.MEETING_BUCKET, meetingFileType.equals(MeetingFileType.OUTLINE_PROJECT_WORD) ? meetingFile.getFilePath() : meetingFile1.getFilePath());
            } catch (Exception e) {
                throw new BIZException("监护大纲word转pdf失败");
            } finally {
                byteArrayOutputStream.close();
            }


        }
        return minIoUtil.genShareLink(MinIoUtil.MEETING_BUCKET, meetingFile.getFilePath());
    }

    @Override
    public HashMap<String, List<OutLineFileDataDTO>> parseFile(String projectId, String projectType) {

        //虚拟文案
        String objectName = "";
//        switch (projectType) {
//            case "1":
//                objectName = "工程信息概况-基坑类.docx";
//                break;
//            case "2":
//                objectName = "工程信息概况-穿越类.docx";
//                break;
//            case "3":
//                objectName = "工程信息概况-【行政许可】市政类 -添加大纲数据.docx";
//                break;
//
//        }
        String projectBaseInfoByProjectId = projectService.getProjectBaseInfoByProjectId(projectId);

        List<String> split = com.google.common.collect.Lists.newArrayList(Splitter.on("/").trimResults()
                .omitEmptyStrings().split(projectBaseInfoByProjectId));


        String fileLink = minIoUtil.genShareLink(split.get(0), split.get(1));


        HashMap<String, List<OutLineFileDataDTO>> kvDataFromFile = outlineProjectCalc.getKVDataFromFile(Integer.valueOf(projectType), fileLink);

        return kvDataFromFile;
    }

    public static void main(String[] args) {
        String suffix = FileNameUtil.getPrefix("d:\\profile.docx");
        System.out.println(suffix);
    }
}
